'''

Case Type： 数据库系统
Case Name： 删除套接字文件，暂停数据库进程（接收kill -19信号）
Create At:  2020/07/27
@zou_jialiang0505328126
Descption:  1. 获取套接字文件路径2. 获取套接字文件名3. 删除套接字文件4. 获取pid5. 停止数据库进程6. 连接数据库7. 恢复数据库进程8. 连接数据库9. 运行tpcc指令10. 恢复socket文件11. 连接数据库

history：
created： 2020/07/27  created by @wan005
'''
import os
import unittest
from yat.test import Node
import time
from yat.test import macro
import sys

sys.path.append(sys.path[0] + "/../")
from testcase.utils.Logger import Logger
from testcase.utils.Constant import Constant
from testcase.utils.Common import Common
from testcase.utils.CommonSH import *
from testcase.utils.ComThread import ComThread

logger = Logger()
common = Common()
Constant = Constant()


class Stop_immediate(unittest.TestCase):
    dbPrimaryUserNode = Node(node='PrimaryDbUser')
    dbPrimaryRootNode = Node(node='PrimaryRoot')
    DB_INSTANCE_PATH = macro.DB_INSTANCE_PATH
    DB_ENV_PATH = macro.DB_ENV_PATH
    GS_CTL_STOP_SUCCESS_MSG = Constant.GS_CTL_STOP_SUCCESS_MSG
    STANDBY_NORMAL = Constant.STANDBY_NORMAL
    PRIMARY_NORMAL = Constant.PRIMARY_NORMAL
    START_SUCCESS_MSG = Constant.START_SUCCESS_MSG
    TPCC_SUCCESS_MSG = Constant.TPCC_SUCCESS_MSG
    RESTART_SUCCESS_MSG = Constant.RESTART_SUCCESS_MSG
    file_name = ''
    file_name_bak = ''
    TPCC_PATH = macro.TPCC_PATH
    primary_sh = CommonSH('PrimaryDbUser')
    standby_1_sh = CommonSH('Standby1DbUser')
    standby_2_sh = CommonSH('Standby2DbUser')
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        logger.info("-----------this is setup-----------")
        logger.info('------------Opengauss_Reliability_Dbsys_Case163.py start------------')

    def test_stop_immediate(self):
        logger.info("----------------------get socket file path--------------")
        sql = "show unix_socket_directory"
        getfilepathMsg = self.primary_sh.executDbSql(sql, )
        logger.info(getfilepathMsg)
        file_path = getfilepathMsg.split('\n')[2]
        logger.info(file_path)

        logger.info("----------------------get socket file name--------------")
        get_file_list_cmd = f'ls -a {file_path}'
        logger.info(get_file_list_cmd)
        file_list = self.dbPrimaryUserNode.sh(get_file_list_cmd).result()
        logger.info(file_list)
        socket_file_name = ''
        for file in file_list.split():
            logger.info(file)
            if (self.dbPrimaryUserNode.db_port not in file) or ('lock' in file):
                pass
            else:
                socket_file_name = file
        logger.info(socket_file_name)
        self.file_name = file_path + "/" + socket_file_name
        self.file_name_bak = self.file_name + '.baktest'

        logger.info("------------------delete socket file----------------------")
        deleteCmd = f'mv {self.file_name} {self.file_name_bak}'
        logger.info(deleteCmd)
        self.dbPrimaryRootNode.sh(deleteCmd)

        logger.info("-----------------------get pid-------------------------------")
        getPidCmd = 'lsof -i:{port}'.replace('{port}', self.dbPrimaryRootNode.db_port)
        pidMsg = self.dbPrimaryRootNode.sh(getPidCmd).result()
        pid = common.getPidFromCmd(str(pidMsg))
        logger.info("-----------------------stop pid-------------------------------")
        stopCmd = f'kill -19 {pid}'
        logger.info(stopCmd)
        self.dbPrimaryRootNode.sh(stopCmd)

        logger.info("----------------------connect opengauss----------------------")
        nosocketConnect = ComThread(self.primary_sh.nosocketConnect, args=())
        nosocketConnect.setDaemon(True)
        nosocketConnect.start()

        socketConnect = ComThread(self.primary_sh.socket_connect, args=(file_path,))
        socketConnect.setDaemon(True)
        socketConnect.start()

        nosocketConnect.join(60 * 5)
        no_socket_connectMsg = nosocketConnect.get_result()
        logger.info('no_socket_connectMsg:' + str(no_socket_connectMsg))
        self.assertIsNone(no_socket_connectMsg)

        socketConnect.join(60 * 5)
        socket_connectMsg = socketConnect.get_result()
        logger.info('socket_connectMsg:' + str(socket_connectMsg))
        self.assertIn(Constant.FAILED_CONNECT_DB, socket_connectMsg)

        logger.info("-----------------------reconnect pid-------------------------------")
        reconnectCmd = f'kill -18 {pid}'
        logger.info(reconnectCmd)
        self.dbPrimaryRootNode.sh(reconnectCmd)

        time.sleep(60)

        logger.info("----------------------connect opengauss----------------------")
        no_socket_connectMsg = self.primary_sh.nosocketConnect()
        logger.info(no_socket_connectMsg)
        self.assertEqual(no_socket_connectMsg, '')

        socket_connectMsg = self.primary_sh.socket_connect(file_path)
        logger.info(socket_connectMsg)
        self.assertIn(Constant.FAILED_CONNECT_DB, socket_connectMsg)

        logger.info("---------------------start TPCC----------------------")
        TPCC_Result = common.startTPCC(self.dbPrimaryRootNode, self.TPCC_PATH)
        logger.info('-------------' + TPCC_Result + '-----------------------')
        logger.info(TPCC_Result)
        self.assertTrue(TPCC_Result.find(self.TPCC_SUCCESS_MSG) > -1)

        logger.info("------------------------recover socket file------------------")
        recoverCmd = f'mv {self.file_name_bak} {self.file_name}'
        logger.info(recoverCmd)
        self.dbPrimaryRootNode.sh(recoverCmd)

        logger.info("----------------------connect opengauss----------------------")
        no_socket_connectMsg = self.primary_sh.nosocketConnect()
        logger.info(no_socket_connectMsg)
        self.assertEqual(no_socket_connectMsg, '')

        socket_connectMsg = self.primary_sh.socket_connect(file_path)
        logger.info(socket_connectMsg)
        logger.info(type(socket_connectMsg))
        self.assertEqual(socket_connectMsg, '')

    def tearDown(self):
        logger.info('----------------this is tearDown-----------------------')
        logger.info("------------------------recover socket file------------------")
        recoverCmd = f'mv {self.file_name_bak} {self.file_name}'
        logger.info(recoverCmd)
        self.dbPrimaryRootNode.sh(recoverCmd)

        # 校验刷脏页是否完成
        logger.info('校验刷脏页是否完成')
        dirty_page_finshed_flag = self.primary_sh.check_whether_remain_dirty_page()
        self.assertTrue(dirty_page_finshed_flag)

        # 校验备机是否完成数据同步
        logger.info('校验备机是否完成数据同步')
        flag_1 = self.standby_1_sh.check_data_consistency()
        self.assertTrue(flag_1)
        flag_2 = self.standby_2_sh.check_data_consistency()
        self.assertTrue(flag_2)
